home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / ipcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-27  |  17.1 KB  |  746 lines

  1. /* IP-related user commands
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  /* Mods by PA0GRI */
  5. #include <stdio.h>
  6. #include "global.h"
  7. #include "config.h"
  8. #include "mbuf.h"
  9. #include "internet.h"
  10. #include "timer.h"
  11. #include "netuser.h"
  12. #include "iface.h"
  13. #include "session.h"
  14. #include "ip.h"
  15. #include "cmdparse.h"
  16. #include "commands.h"
  17. #include "rip.h"
  18. #include "rspf.h"
  19. #include "domain.h"
  20. #include "pktdrvr.h"
  21.  
  22. int32 Ip_addr;
  23. int Route_Sort=1;
  24.  
  25. static int doadd __ARGS((int argc,char *argv[],void *p));
  26. #ifdef  IPACCESS
  27. static int doaccess __ARGS((int argc,char *argv[],void *p));
  28. #endif
  29. static int dodrop __ARGS((int argc,char *argv[],void *p));
  30. static int doflush __ARGS((int argc,char *argv[],void *p));
  31. static int doipaddr __ARGS((int argc,char *argv[],void *p));
  32. static int doipstat __ARGS((int argc,char *argv[],void *p));
  33. static int dolook __ARGS((int argc,char *argv[],void *p));
  34. static int dortimer __ARGS((int argc,char *argv[],void *p));
  35. static int dottl __ARGS((int argc,char *argv[],void *p));
  36. int doipheard __ARGS((int argc,char *argv[],void *p));
  37. static int doiphport __ARGS((int argc,char *argv[],void *p));
  38. static int doiphsize __ARGS((int argc,char *argv[],void *p));
  39. void dumproute __ARGS((struct route *rp,char *p));
  40. static int doroutesort __ARGS((int argc,char *argv[],void *p));
  41.  
  42. static struct cmds DFAR Ipcmds[] = {
  43. #ifdef  IPACCESS
  44.     "access",       doaccess,       0,      0, NULLCHAR,
  45. #endif
  46.     "address",      doipaddr,       0,      0, NULLCHAR,
  47.     "heard",        doipheard,      0,      0, NULLCHAR,
  48.     "hport",        doiphport,      0,      0, NULLCHAR,
  49.     "hsize",        doiphsize,      0,      0, NULLCHAR,
  50.     "rtimer",       dortimer,       0,      0, NULLCHAR,
  51.     "status",       doipstat,       0,      0, NULLCHAR,
  52.     "ttl",          dottl,          0,      0, NULLCHAR,
  53.     NULLCHAR,
  54. };
  55. /* "route" subcommands */
  56. static struct cmds Rtcmds[] = {
  57.     "add",          doadd,          0,      3,
  58.     "route add <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]",
  59.  
  60.     "addprivate",   doadd,          0,      3,
  61.     "route addprivate <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]",
  62.  
  63.     "drop",         dodrop,         0,      2,
  64.     "route drop <dest addr>[/<bits>]",
  65.  
  66.     "flush",        doflush,        0,      0,
  67.     NULLCHAR,
  68.  
  69.     "lookup",       dolook,         0,      2,
  70.     "route lookup <dest addr>",
  71.     
  72.     "sort",         doroutesort,    0,      0,
  73.     NULLCHAR,
  74.  
  75.     NULLCHAR,
  76. };
  77.  
  78. int
  79. doip(argc,argv,p)
  80. int argc;
  81. char *argv[];
  82. void *p;
  83. {
  84.     return subcmd(Ipcmds,argc,argv,p);
  85. }
  86. #ifdef  IPACCESS
  87. static int
  88. doaccess(argc,argv,p)
  89. int argc;
  90. char *argv[];
  91. void *p;
  92. {
  93.     struct iface *ifp;
  94.     int32 source,target;
  95.     unsigned sbits,tbits;
  96.     char *bitp;
  97.     int16 lport,hport,protocol,state;
  98.     char *cp; /* for printing the table */
  99.     struct rtaccess *tpacc;
  100.     struct rtaccess *btacc;
  101.     struct rtaccess *bfacc;
  102.     struct rtaccess *head;
  103.     char tmpbuf[15];
  104.  
  105.     if(argc == 1){ /* print out the table */
  106.         tprintf("Source Address  Len Dest Address    Len Interface    Proto Low   High  State\n");
  107.         for(tpacc = IPaccess;tpacc != NULLACCESS;tpacc = tpacc->nxtiface){
  108.             for(btacc = tpacc;btacc != NULLACCESS;btacc = btacc->nxtbits){
  109.                 if(btacc->source != 0)
  110.                     cp = inet_ntoa(btacc->source);
  111.                 else
  112.                     cp = "all";
  113.                 tprintf("%-16s",cp);
  114.                 tprintf("%2u  ",btacc->sbits);
  115.                 if(btacc->target != 0)
  116.                     cp = inet_ntoa(btacc->target);
  117.                 else
  118.                     cp = "all";
  119.                 tprintf("%-16s",cp);
  120.                 tprintf("%2u  ",btacc->bits);
  121.                 tprintf("%-13s",btacc->iface->name);
  122.                 switch (btacc->protocol) {
  123.                     case 0:
  124.                         cp = "any";
  125.                         break;
  126.                     case ICMP_PTCL:
  127.                         cp = "icmp";
  128.                         break;
  129.                     case TCP_PTCL:
  130.                         cp = "tcp";
  131.                         break;
  132.                     case UDP_PTCL:
  133.                         cp = "udp";
  134.                         break;
  135.                     default:
  136.                         cp = itoa(btacc->protocol,tmpbuf,10);
  137.                 }
  138.                 tprintf("%-5s ",cp);
  139.                 tprintf("%5u ",btacc->lowport);
  140.                 tprintf("%5u ",btacc->highport);
  141.                 if(btacc->status)
  142.                     cp = "deny";
  143.                 else
  144.                     cp = "permit";
  145.                 tprintf("%-6s\n",cp);
  146.             }
  147.         }
  148.         return 0;
  149.     }
  150.  
  151.     if(strcmp(argv[1],"permit") == 0){
  152.         state = 0;
  153.     } else {
  154.         if((strcmp(argv[1],"deny") == 0) 
  155.         || (strcmp(argv[1],"delete") == 0)){
  156.             state = -1;
  157.         } else {
  158.             tprintf(" Format: ip access <permit|deny|delete> <proto> <src addr>[/<bits>] <dest addr>[/<bits>] <if name> [low [high]]\n");
  159.             return 1;
  160.         }
  161.     }
  162.  
  163.     switch (*argv[2]){
  164.         case 'a':    /* ANY */
  165.             protocol = 0;
  166.             break;
  167.         case 'i':    /* ICMP */
  168.             protocol = ICMP_PTCL;
  169.             break;
  170.         case 't':    /* TCP */
  171.             protocol = TCP_PTCL;
  172.             break;
  173.         case 'u':    /* UDP */
  174.             protocol = UDP_PTCL;
  175.             break;
  176.         default:
  177.             protocol = atoi(argv[2]);
  178.     }
  179.  
  180.     if(strcmp(argv[3],"all") == 0){
  181.         source = 0;
  182.         sbits = 0;
  183.     } else {
  184.         /* If IP address is followed by an optional slash and
  185.          * a length field, (e.g., 128.96/16) get it;
  186.          * otherwise assume a full 32-bit address
  187.          */
  188.         if((bitp = strchr(argv[3],'/')) != NULLCHAR){
  189.             /* Terminate address token for resolve() call */
  190.             *bitp++ = '\0';
  191.             sbits = atoi(bitp);
  192.         } else
  193.             sbits = 32;
  194.  
  195.         if((source = resolve(argv[3])) == 0){
  196.             tprintf(Badhost,argv[3]);
  197.             return 1;
  198.         }
  199.     }
  200.     if(strcmp(argv[4],"all") == 0){
  201.         target = 0;
  202.         tbits = 0;
  203.     } else {
  204.         if((bitp = strchr(argv[4],'/')) != NULLCHAR){
  205.             *bitp++ = '\0';
  206.             tbits = atoi(bitp);
  207.         } else
  208.             tbits = 32;
  209.  
  210.         if((target = resolve(argv[4])) == 0){
  211.             tprintf(Badhost,argv[4]);
  212.             return 1;
  213.         }
  214.     }
  215.     
  216.     if((ifp = if_lookup(argv[5])) == NULLIF){
  217.         tprintf(Badinterface,argv[5]);
  218.         return 1;
  219.     }
  220.  
  221.     if(((protocol != TCP_PTCL) && (protocol != UDP_PTCL)) || (argc < 7)) {
  222.         lport = 0;
  223.         hport = 0;
  224.     } else {
  225.         if(strcmp(argv[6],"all") == 0){
  226.             lport = 0;
  227.         } else {
  228.             lport = atoi(argv[6]);
  229.         }
  230.         if((argc < 8) || (lport == 0))
  231.             hport = lport;
  232.         else
  233.             hport = atoi(argv[7]);
  234.     }
  235.  
  236.     if(strcmp(argv[1],"delete") == 0){
  237.         head = IPaccess;
  238.         for(tpacc = IPaccess;tpacc != NULLACCESS;head = tpacc,tpacc = tpacc->nxtiface){
  239.             if(tpacc->iface == ifp){
  240.                 for(btacc = tpacc;btacc != NULLACCESS;
  241.                      head = btacc,btacc = btacc->nxtbits){
  242.                     if((btacc->protocol == protocol) &&
  243.                        (btacc->source == source)     &&
  244.                        (btacc->sbits == sbits)       &&
  245.                        (btacc->target == target)     &&
  246.                        (btacc->bits == tbits)        &&
  247.                        (btacc->lowport == lport)     &&
  248.                        (btacc->highport == hport)) { /*match*/
  249.                         bfacc = btacc; /* save to unalloc */
  250.                 /*now delete. watch for special cases*/
  251.                         if(btacc != tpacc){ /* not at head of list */
  252.                          head->nxtbits = btacc->nxtbits;
  253.                             free(bfacc);
  254.                             return 0;
  255.                         }
  256.                         if(btacc == IPaccess){ /* real special case */
  257.                         if(IPaccess->nxtbits == NULLACCESS)
  258.                             IPaccess = btacc->nxtiface;
  259.                         else {
  260.                             IPaccess = btacc->nxtbits;
  261.                             (btacc->nxtbits)->nxtiface = btacc->nxtiface;
  262.                         }
  263.                         } else { /* we know tpacc=btacc <> IPaccess */
  264.                         if(btacc->nxtbits == NULLACCESS)
  265.                             head->nxtiface = btacc->nxtiface;
  266.                         else {
  267.                             head->nxtiface = btacc->nxtbits;
  268.                             (btacc->nxtbits)->nxtiface = btacc->nxtiface;
  269.                         }
  270.                         }
  271.                     free(bfacc);
  272.                     return 0;
  273.                     }
  274.                 }
  275.             }
  276.         }
  277.         tprintf("Not found.\n");
  278.         return 1;
  279.     }
  280.     /* add the access */
  281.     addaccess(protocol,source,sbits,target,tbits,ifp,lport,hport,state);
  282.     return 0;
  283. }
  284. #endif
  285. static int
  286. doipaddr(argc,argv,p)
  287. int argc;
  288. char *argv[];
  289. void *p;
  290. {
  291.     int32 n;
  292.  
  293.     if(argc < 2) {
  294.         tprintf("%s\n",inet_ntoa(Ip_addr));
  295.     } else if((n = resolve(argv[1])) == 0){
  296.         tprintf(Badhost,argv[1]);
  297.         return 1;
  298.     } else
  299.         Ip_addr = n;
  300.     return 0;
  301. }
  302. static int
  303. dortimer(argc,argv,p)
  304. int argc;
  305. char *argv[];
  306. void *p;
  307. {
  308.     return setlong(&ipReasmTimeout,"IP reasm timeout (sec)",argc,argv);
  309. }
  310. static int
  311. dottl(argc,argv,p)
  312. int argc;
  313. char *argv[];
  314. void *p;
  315. {
  316.     return setlong(&ipDefaultTTL,"IP Time-to-live",argc,argv);
  317. }
  318.  
  319.  
  320. char RouteHeader[] = "Destination      Len Interface Gateway          Metric P Timer  Use\n";
  321.  
  322. /* Display and/or manipulate routing table */
  323. int
  324. doroute(argc,argv,p)
  325. int argc;
  326. char *argv[];
  327. void *p;
  328. {
  329.     register int i,j,k,l,m,bits,numflg,flow_tmp;
  330.     register struct route *rp;
  331.     char *temp,temp2[80];
  332.  
  333.     if(argc >= 2)
  334.         return subcmd(Rtcmds,argc,argv,p);
  335.  
  336.     /* Dump IP routing table
  337.      * Dest            Len Interface    Gateway          Use
  338.      * 192.001.002.003 32  sl0          192.002.003.004  0
  339.      * modified for Sorted output - D. Crompton 2.92
  340.      */
  341.       
  342.     flow_tmp=Current->flowmode;
  343.     Current->flowmode=1;
  344.     
  345.     tputs(RouteHeader);
  346.  
  347.     for(j=0,bits=31;bits>=0;bits--)
  348.        for(i=0;i<HASHMOD;i++)
  349.           for(rp = Routes[bits][i];rp != NULLROUTE;j++,rp = rp->next);
  350.  
  351.     if (j){
  352.     
  353.       temp=mallocw(j*80);
  354.  
  355.       for(bits=31,k=0;bits>=0;bits--)
  356.         for(i=0;i<HASHMOD;i++)
  357.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next,k+=80)
  358.                 dumproute(rp,&temp[k]);
  359.       
  360.       if (Route_Sort) qsort(temp,(size_t)j,80,strcmp);              
  361.     
  362.       for (i=0,k=4;i<j;i++,k+=80) {
  363.           tprintf("%s",&temp[k]);
  364.           if (tprintf("\n") == EOF)
  365.              {
  366.               Current->flowmode=flow_tmp;
  367.               free(temp);
  368.               return 0;
  369.              }
  370.       }
  371.      free(temp);
  372.     }
  373.     if(R_default.iface != NULLIF){
  374.         dumproute(&R_default,temp2);
  375.         tprintf("%s\n",temp2);
  376.      }
  377.     Current->flowmode = flow_tmp;
  378.     return 0;
  379. }
  380.  
  381. /* Dump a routing table entry */
  382. void
  383. dumproute(rp,temp)
  384. register struct route *rp;
  385. char *temp;
  386. {
  387.     char *cp;
  388.     unsigned int a=0;
  389.     char *name;                      
  390.  
  391.     if(rp->target != 0) {
  392.         if(DTranslate && (name = resolve_a(rp->target,!DVerbose)) != NULLCHAR) {
  393.             a+=4;
  394.             strcpy(temp,name);
  395.             free(name);
  396.         } else {    
  397.             cp = inet_ntobos(rp->target);
  398.             a=sprintf(temp,"%4s",cp);
  399.         }
  400.         cp = inet_ntoa(rp->target);
  401.     } else {
  402.         cp = "default";
  403.     }
  404.     a+=sprintf(&temp[a],"%-16.16s ",cp);
  405.     a+=sprintf(&temp[a],"%-4u",rp->bits);
  406.     a+=sprintf(&temp[a],"%-9.9s ",rp->iface->name);
  407.     if(rp->gateway != 0)
  408.         cp = inet_ntoa(rp->gateway);
  409.     else
  410.         cp = "";
  411.     a+=sprintf(&temp[a],"%-16.16s ",cp);
  412.     a+=sprintf(&temp[a],"%-6lu ",rp->metric);
  413.     a+=sprintf(&temp[a],"%c ",(rp->flags & RTPRIVATE) ? 'P' : ' ');
  414.     if(rp->timer.state == TIMER_STOP){
  415.         if(rp->timer.duration == 1) a+=sprintf(&temp[a],"rspf   ");
  416.         else a+=sprintf(&temp[a],"man    ");
  417.     } else {
  418.         a+=sprintf(&temp[a],"%-7lu",read_timer(&rp->timer) / 1000L);
  419.     }
  420.     sprintf(&temp[a],"%lu",rp->uses);
  421. }
  422.  
  423.  
  424. /* Sort Route dump */
  425. static int
  426. doroutesort(argc,argv,p)
  427. int argc ;
  428. char *argv[] ;
  429. void *p;
  430. {
  431.     extern int Route_Sort;
  432.  
  433.     return setbool(&Route_Sort,"Route Sort flag",argc,argv);
  434. }
  435.  
  436.  
  437. /* Add an entry to the routing table
  438.  * E.g., "add 1.2.3.4 ax0 5.6.7.8 3"
  439.  */
  440. static int
  441. doadd(argc,argv,p)
  442. int argc;
  443. char *argv[];
  444. void *p;
  445. {
  446.     struct iface *ifp;
  447.     int32 dest,gateway;
  448.     unsigned bits;
  449.     char *bitp;
  450.     int32 metric;
  451.     char private;
  452.  
  453.     if(strncmp(argv[0],"addp",4) == 0)
  454.         private = 1;
  455.     else
  456.         private = 0;
  457.     if(strcmp(argv[1],"default") == 0){
  458.         dest = 0L;
  459.         bits = 0;
  460.     } else {
  461.         /* If IP address is followed by an optional slash and
  462.          * a length field, (e.g., 128.96/16) get it;
  463.          * otherwise assume a full 32-bit address
  464.          */
  465.         if((bitp = strchr(argv[1],'/')) != NULLCHAR){
  466.             /* Terminate address token for resolve() call */
  467.             *bitp++ = '\0';
  468.             bits = atoi(bitp);
  469.         } else
  470.             bits = 32;
  471.  
  472.         if((dest = resolve(argv[1])) == 0){
  473.             tprintf(Badhost,argv[1]);
  474.             return 1;
  475.         }
  476.     }
  477.     if((ifp = if_lookup(argv[2])) == NULLIF){
  478.     tprintf(Badinterface,argv[2]);
  479.         return 1;
  480.     }
  481.  
  482.     metric = 1;
  483.  
  484.     if(argc > 3){
  485.         /* Next "trick is needed to set the metric on subnets
  486.          * higher as the default 1 for rspf.
  487.          * route add subnet/bits iface default 10  
  488.          */
  489.         if(strcmp(argv[3],"direct") == 0){      /* N1BEE */
  490.             gateway = 0;
  491.         /* calculate a nice metric based on subnet mask size */
  492.             if(bits != 0 && bits < 32)
  493.                 metric = (39 - bits) * 5 / 17;
  494.         } else {
  495.             if((gateway = resolve(argv[3])) == 0){
  496.                 tprintf(Badhost,argv[3]);
  497.                 return 1;
  498.             }
  499.         }
  500.     } else {
  501.         gateway = 0;
  502.     }
  503.     if (argc > 4)
  504.         metric = atol(argv[4]);
  505.  
  506.     if(rt_add(dest,bits,gateway,ifp,metric,0,private) == NULLROUTE)
  507.         tprintf("Can't add route\n");
  508. #ifdef  RSPF
  509.     if(!private)
  510.         rspfrouteupcall(dest,bits,gateway);     /* Do an RSPF upcall */
  511. #endif  /* RSPF */
  512.     return 0;
  513. }
  514. /* Drop an entry from the routing table
  515.  * E.g., "drop 128.96/16
  516.  */
  517. static int
  518. dodrop(argc,argv,p)
  519. int argc;
  520. char *argv[];
  521. void *p;
  522. {
  523.     char *bitp;
  524.     unsigned bits;
  525.     int32 n;
  526.  
  527.     if(strcmp(argv[1],"default") == 0){
  528.         n = 0L;
  529.         bits = 0;
  530.     } else {
  531.         /* If IP address is followed by an optional slash and length field,
  532.          * (e.g., 128.96/16) get it; otherwise assume a full 32-bit address
  533.          */
  534.         if((bitp = strchr(argv[1],'/')) != NULLCHAR){
  535.             /* Terminate address token for resolve() call */
  536.             *bitp++ = '\0';
  537.             bits = atoi(bitp);
  538.         } else
  539.             bits = 32;
  540.  
  541.         if((n = resolve(argv[1])) == 0){
  542.             tprintf(Badhost,argv[1]);
  543.             return 1;
  544.         }
  545.     }
  546.     return rt_drop(n,bits);
  547. }
  548. /* Force a timeout on all temporary routes */
  549. static int
  550. doflush(argc,argv,p)
  551. int argc;
  552. char *argv[];
  553. void *p;
  554. {
  555.     register struct route *rp;
  556.     struct route *rptmp;
  557.     int i,j;
  558.     
  559.     if(R_default.timer.state == TIMER_RUN){
  560.         rt_drop(0,0);   /* Drop default route */
  561.     }
  562.     for(i=0;i<HASHMOD;i++){
  563.         for(j=0;j<32;j++){
  564.             for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
  565.                 rptmp = rp->next;
  566.                 if(rp->timer.state == TIMER_RUN){
  567.                     rt_drop(rp->target,rp->bits);
  568.                 }
  569.             }
  570.         }
  571.     }
  572.     return 0;
  573. }
  574.  
  575. static int
  576. dolook(argc,argv,p)
  577. int argc;
  578. char *argv[];
  579. void *p;
  580. {
  581.     struct route *rp;
  582.     int32 addr;
  583.     char temp[80];
  584.  
  585.     addr = resolve(argv[1]);
  586.     if(addr == 0){
  587.     tprintf(Badhost,argv[1]);
  588.         return 1;
  589.     }
  590.     if((rp = rt_lookup(addr)) == NULLROUTE){
  591.         tprintf("Host %s (%s) unreachable\n",argv[1],inet_ntoa(addr));
  592.         return 1;
  593.     }
  594.     
  595.     dumproute(rp,temp);
  596.     tputs(RouteHeader);
  597.     tprintf("%s\n",&temp[4]);
  598.     
  599.     return 0;
  600. }
  601.  
  602. static int
  603. doipstat(argc,argv,p)
  604. int argc;
  605. char *argv[];
  606. void *p;
  607. {
  608.     register struct reasm *rp;
  609.     register struct frag *fp;
  610.     int i;
  611.  
  612.     for(i=1;i<=NUMIPMIB;i++){
  613.         tprintf("(%2u)%-20s%10lu",i,
  614.          Ip_mib[i].name,Ip_mib[i].value.integer);
  615.         if(i % 2)
  616.             tprintf("     ");
  617.         else
  618.             tprintf("\n");
  619.     }
  620.     if((i % 2) == 0)
  621.         tprintf("\n");
  622.  
  623.     if(Reasmq != NULLREASM)
  624.         tprintf("Reassembly fragments:\n");
  625.     for(rp = Reasmq;rp != NULLREASM;rp = rp->next){
  626.         tprintf("src %s",inet_ntoa(rp->source));
  627.         tprintf(" dest %s",inet_ntoa(rp->dest));
  628.         if(tprintf(" id %u pctl %u time %lu len %u\n",
  629.          rp->id,uchar(rp->protocol),read_timer(&rp->timer),
  630.          rp->length) == EOF)
  631.             break;
  632.         for(fp = rp->fraglist;fp != NULLFRAG;fp = fp->next){
  633.             if(tprintf(" offset %u last %u\n",fp->offset,
  634.             fp->last) == EOF)
  635.                 break;
  636.         }
  637.     }
  638.     return 0;
  639. }
  640.  
  641. /* IP heard logging - WG7J */
  642. static struct iph *iph_create __ARGS((int32 addr));
  643. static struct iph *iph_lookup __ARGS((int32 addr));
  644. struct iph *Iph;
  645.  
  646. static int Maxipheard = MAXIPHEARD;
  647.  
  648. static int doiphsize(argc,argv,p)
  649. int argc;
  650. char *argv[];
  651. void *p;
  652. {
  653.     return setint(&Maxipheard,"Max ip-heard",argc,argv);
  654. }
  655.  
  656. /* Configure a port to do ip-heard logging */
  657. static int
  658. doiphport(argc,argv,p)
  659. int argc;
  660. char *argv[];
  661. void *p;
  662. {
  663.     return(dosetflag(argc,argv,p,LOG_IPHEARD, 0));
  664. }
  665.  
  666. int
  667. doipheard(argc, argv, p)
  668. int argc;
  669. char *argv[];
  670. void *p;
  671. {
  672.     struct iph *iph;
  673.  
  674.     if(tputs("Tcp/Ip systems heard:\nAddress                Port       Since       Pkts\n") == EOF)
  675.         return EOF;
  676.     for(iph=Iph;iph;iph=iph->next) {
  677.         if(tprintf("%-22s %-8s %12s %5d\n",inet_ntoa(iph->addr),iph->iface->name,
  678.             tformat(secclock() - iph->time),iph->count) == EOF)
  679.             return EOF;
  680.     }
  681.     return 0;
  682. }
  683.  
  684. void
  685. log_ipheard(addr,ifp)
  686. int32 addr;
  687. struct iface *ifp;
  688. {
  689.     struct iph *niph;
  690.  
  691.     if((niph = iph_lookup(addr)) == NULLIPH)
  692.         if((niph = iph_create(addr)) == NULLIPH)
  693.             return;
  694.     niph->iface = ifp;
  695.     niph->count++;
  696.     niph->time = secclock();
  697. }
  698.  
  699. /* Look up an entry in the ip data base */
  700. struct iph *
  701. iph_lookup(addr)
  702. int32 addr;
  703. {
  704.     register struct iph *ip;
  705.     struct iph *last = NULLIPH;
  706.  
  707.     for(ip = Iph;ip != NULLIPH;last = ip,ip = ip->next){
  708.         if(ip->addr == addr) {
  709.             if(last != NULLIPH){
  710.                 /* Move entry to top of list */
  711.                 last->next = ip->next;
  712.                 ip->next = Iph;
  713.                 Iph = ip;
  714.             }
  715.             return ip;
  716.         }
  717.     }
  718.     return NULLIPH;
  719. }
  720.  
  721. /* Create a new entry in the source database */
  722. /* If there are too many entries, override the oldest one - WG7J */
  723. static struct iph *
  724. iph_create(addr)
  725. int32 addr;
  726. {
  727.     static int numdb;
  728.     register struct iph *iph;
  729.     struct iph *last = NULLIPH;
  730.  
  731.     if(Maxipheard && numdb == Maxipheard) {
  732.         /* find and use last one in list */
  733.         for(iph = Iph;iph->next != NULLIPH;last = iph,iph = iph->next);
  734.         /* delete entry from end */
  735.         last->next = NULLIPH;
  736.     } else {    /* create a new entry */
  737.         numdb++;
  738.         iph = (struct iph *)callocw(1,sizeof(struct iph));
  739.     }
  740.     iph->addr = addr;
  741.     iph->next = Iph;
  742.     Iph = iph;
  743.  
  744.     return iph;
  745. }
  746.